{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"https://colab.research.google.com/github/enzoampil/fastquant/blob/master/examples/backtest_disclosures.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# uncomment to install in colab\n",
    "# !pip install -e git+https://github.com/enzoampil/fastquant.git@master#egg=fastquant"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Company disclosures-based trading strategy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Pulling JFC disclosures summary...\n",
      "3 pages detected!\n",
      "Found 145 disclosures between 01-01-2015 & 07-15-2020 with 16 types:\n",
      "['Material Information/Transactions'\n",
      " \"Notice of Annual or Special Stockholders' Meeting\" 'Press Release'\n",
      " \"Notice of Analysts'/Investors' Briefing\" 'Declaration of Cash Dividends'\n",
      " 'Joint Ventures' 'Change in Corporate Contact Details and/or Website'\n",
      " 'Substantial Acquisitions' 'Clarification of News Reports'\n",
      " \"Results of Annual or Special Stockholders' Meeting\"\n",
      " 'Results of Organizational Meeting of Board of Directors'\n",
      " 'Acquisition or Disposition of Shares of Another Corporation'\n",
      " 'Change in Directors and/or Officers (Resignation, Removal or Appointment, Election and/or Promotion)'\n",
      " 'Amendments to By-Laws' 'Amendments to Articles of Incorporation'\n",
      " 'Update on Corporate Actions/Material Transactions/Agreements']\n",
      "Pulling details in all JFC disclosures...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 1/1 [00:00<00:00,  6.50it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded: /home/jgendrinal/rprojects/fastquant/examples/src/fastquant/python/fastquant/data/JFC_disclosures_01-01-2015_07-15-2020.csv\n"
     ]
    }
   ],
   "source": [
    "from fastquant import DisclosuresPSE\n",
    "\n",
    "dpse = DisclosuresPSE(\"JFC\", start_date=\"01-01-2015\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Company Name</th>\n",
       "      <th>Template Name</th>\n",
       "      <th>PSE Form Number</th>\n",
       "      <th>Announce Date and Time</th>\n",
       "      <th>Circular Number</th>\n",
       "      <th>edge_no</th>\n",
       "      <th>url</th>\n",
       "      <th>disclosure_table</th>\n",
       "      <th>Background/Description of the Disclosure</th>\n",
       "      <th>Subject of the Disclosure</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>[Amend-1]Material Information/Transactions</td>\n",
       "      <td>4-30</td>\n",
       "      <td>2020-06-25 07:37:00</td>\n",
       "      <td>C04444-2020</td>\n",
       "      <td>68f4aa3616d6457c0de8473cebbd6407</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"Common\", \"Subject of ...</td>\n",
       "      <td>Jollibee Foods Corporation (JFC, the “Guaranto...</td>\n",
       "      <td>JFC to Issue US$ 600 Million 5.5 and 10 Year N...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>Material Information/Transactions</td>\n",
       "      <td>4-30</td>\n",
       "      <td>2020-06-19 08:01:00</td>\n",
       "      <td>C04295-2020</td>\n",
       "      <td>0be4ceaf09ea28090de8473cebbd6407</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"COMMON\", \"Subject of ...</td>\n",
       "      <td>Golden Plate Pte. Ltd. (GPPL), a wholly owned ...</td>\n",
       "      <td>Jollibee Foods Corporation (JFC) and Dim Sum P...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>Material Information/Transactions</td>\n",
       "      <td>4-30</td>\n",
       "      <td>2020-06-17 10:39:00</td>\n",
       "      <td>C04227-2020</td>\n",
       "      <td>d1a0237ac4559bda0de8473cebbd6407</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"COMMON\", \"Subject of ...</td>\n",
       "      <td>Jollibee Foods Corporation (JFC) announced tha...</td>\n",
       "      <td>Cash dividend declaration</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>Notice of Annual or Special Stockholders' Meeting</td>\n",
       "      <td>7-1</td>\n",
       "      <td>2020-05-28 07:23:00</td>\n",
       "      <td>C03757-2020</td>\n",
       "      <td>3d7278efdfc3720b0de8473cebbd6407</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"COMMON\", \"Subject of ...</td>\n",
       "      <td>In compliance with National Telecommunication ...</td>\n",
       "      <td>Update of Corporate Contact Details</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>Press Release</td>\n",
       "      <td>4-31</td>\n",
       "      <td>2020-05-28 07:17:00</td>\n",
       "      <td>C03749-2020</td>\n",
       "      <td>55ee488e963620db0de8473cebbd6407</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"COMMON\", \"Subject of ...</td>\n",
       "      <td>Further to its May 8, 2018 disclosure, JFC dis...</td>\n",
       "      <td>JFC to increase investment in Buyer of Tim Ho ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>140</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>Declaration of Cash Dividends</td>\n",
       "      <td>6-1</td>\n",
       "      <td>2015-04-08 08:39:00</td>\n",
       "      <td>C01729-2015</td>\n",
       "      <td>49a8d6ba7f7608fcb15effbf9088d1ab</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"Common\", \"Subject of ...</td>\n",
       "      <td>Jollibee Worldwide Pte. Ltd., (the “Issuer”), ...</td>\n",
       "      <td>JFC Mandates Banks for U.S.$ Senior Unsecured ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>141</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>Press Release</td>\n",
       "      <td>4-31</td>\n",
       "      <td>2015-02-23 13:41:00</td>\n",
       "      <td>C00789-2015</td>\n",
       "      <td>929338ec12042f71b15effbf9088d1ab</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"COMMON\", \"Subject of ...</td>\n",
       "      <td>Notice of annual stockholders' meeting for the...</td>\n",
       "      <td>Notice of annual stockholders' meeting for the...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>142</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>Clarification of News Reports</td>\n",
       "      <td>4-13</td>\n",
       "      <td>2015-01-22 14:28:00</td>\n",
       "      <td>C00256-2015</td>\n",
       "      <td>7578082745af0a94b15effbf9088d1ab</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"Common\", \"Subject of ...</td>\n",
       "      <td>JFC Announces First Quarter 2020 Financial Res...</td>\n",
       "      <td>Press Release: 2020 1st Quarter Financial Results</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>143</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>Update on Corporate Actions/Material Transacti...</td>\n",
       "      <td>16-1</td>\n",
       "      <td>2015-01-09 13:24:00</td>\n",
       "      <td>C00092-2015</td>\n",
       "      <td>09cd76ec59b47b6db15effbf9088d1ab</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"Common\", \"Subject of ...</td>\n",
       "      <td>Jollibee Foods Corporation, one of Asia's larg...</td>\n",
       "      <td>JFC to Spend Php7 Billion for Business Transfo...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>144</th>\n",
       "      <td>Jollibee Foods Corporation</td>\n",
       "      <td>Update on Corporate Actions/Material Transacti...</td>\n",
       "      <td>16-1</td>\n",
       "      <td>2015-01-06 07:51:00</td>\n",
       "      <td>C00024-2015</td>\n",
       "      <td>56a1e05383b8fec9b15effbf9088d1ab</td>\n",
       "      <td>https://edge.pse.com.ph/openDiscViewer.do?edge...</td>\n",
       "      <td>{\"Title of Each Class\": \"common \", \"Subject of...</td>\n",
       "      <td>Jollibee Foods Corporation will do an Earnings...</td>\n",
       "      <td>JFC’s Earnings Call for its First Quarter 2020...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>145 rows × 10 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                   Company Name  \\\n",
       "0    Jollibee Foods Corporation   \n",
       "1    Jollibee Foods Corporation   \n",
       "2    Jollibee Foods Corporation   \n",
       "3    Jollibee Foods Corporation   \n",
       "4    Jollibee Foods Corporation   \n",
       "..                          ...   \n",
       "140  Jollibee Foods Corporation   \n",
       "141  Jollibee Foods Corporation   \n",
       "142  Jollibee Foods Corporation   \n",
       "143  Jollibee Foods Corporation   \n",
       "144  Jollibee Foods Corporation   \n",
       "\n",
       "                                         Template Name PSE Form Number  \\\n",
       "0           [Amend-1]Material Information/Transactions            4-30   \n",
       "1                    Material Information/Transactions            4-30   \n",
       "2                    Material Information/Transactions            4-30   \n",
       "3    Notice of Annual or Special Stockholders' Meeting             7-1   \n",
       "4                                        Press Release            4-31   \n",
       "..                                                 ...             ...   \n",
       "140                      Declaration of Cash Dividends             6-1   \n",
       "141                                      Press Release            4-31   \n",
       "142                      Clarification of News Reports            4-13   \n",
       "143  Update on Corporate Actions/Material Transacti...            16-1   \n",
       "144  Update on Corporate Actions/Material Transacti...            16-1   \n",
       "\n",
       "    Announce Date and Time Circular Number                           edge_no  \\\n",
       "0      2020-06-25 07:37:00     C04444-2020  68f4aa3616d6457c0de8473cebbd6407   \n",
       "1      2020-06-19 08:01:00     C04295-2020  0be4ceaf09ea28090de8473cebbd6407   \n",
       "2      2020-06-17 10:39:00     C04227-2020  d1a0237ac4559bda0de8473cebbd6407   \n",
       "3      2020-05-28 07:23:00     C03757-2020  3d7278efdfc3720b0de8473cebbd6407   \n",
       "4      2020-05-28 07:17:00     C03749-2020  55ee488e963620db0de8473cebbd6407   \n",
       "..                     ...             ...                               ...   \n",
       "140    2015-04-08 08:39:00     C01729-2015  49a8d6ba7f7608fcb15effbf9088d1ab   \n",
       "141    2015-02-23 13:41:00     C00789-2015  929338ec12042f71b15effbf9088d1ab   \n",
       "142    2015-01-22 14:28:00     C00256-2015  7578082745af0a94b15effbf9088d1ab   \n",
       "143    2015-01-09 13:24:00     C00092-2015  09cd76ec59b47b6db15effbf9088d1ab   \n",
       "144    2015-01-06 07:51:00     C00024-2015  56a1e05383b8fec9b15effbf9088d1ab   \n",
       "\n",
       "                                                   url  \\\n",
       "0    https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "1    https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "2    https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "3    https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "4    https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "..                                                 ...   \n",
       "140  https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "141  https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "142  https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "143  https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "144  https://edge.pse.com.ph/openDiscViewer.do?edge...   \n",
       "\n",
       "                                      disclosure_table  \\\n",
       "0    {\"Title of Each Class\": \"Common\", \"Subject of ...   \n",
       "1    {\"Title of Each Class\": \"COMMON\", \"Subject of ...   \n",
       "2    {\"Title of Each Class\": \"COMMON\", \"Subject of ...   \n",
       "3    {\"Title of Each Class\": \"COMMON\", \"Subject of ...   \n",
       "4    {\"Title of Each Class\": \"COMMON\", \"Subject of ...   \n",
       "..                                                 ...   \n",
       "140  {\"Title of Each Class\": \"Common\", \"Subject of ...   \n",
       "141  {\"Title of Each Class\": \"COMMON\", \"Subject of ...   \n",
       "142  {\"Title of Each Class\": \"Common\", \"Subject of ...   \n",
       "143  {\"Title of Each Class\": \"Common\", \"Subject of ...   \n",
       "144  {\"Title of Each Class\": \"common \", \"Subject of...   \n",
       "\n",
       "              Background/Description of the Disclosure  \\\n",
       "0    Jollibee Foods Corporation (JFC, the “Guaranto...   \n",
       "1    Golden Plate Pte. Ltd. (GPPL), a wholly owned ...   \n",
       "2    Jollibee Foods Corporation (JFC) announced tha...   \n",
       "3    In compliance with National Telecommunication ...   \n",
       "4    Further to its May 8, 2018 disclosure, JFC dis...   \n",
       "..                                                 ...   \n",
       "140  Jollibee Worldwide Pte. Ltd., (the “Issuer”), ...   \n",
       "141  Notice of annual stockholders' meeting for the...   \n",
       "142  JFC Announces First Quarter 2020 Financial Res...   \n",
       "143  Jollibee Foods Corporation, one of Asia's larg...   \n",
       "144  Jollibee Foods Corporation will do an Earnings...   \n",
       "\n",
       "                             Subject of the Disclosure  \n",
       "0    JFC to Issue US$ 600 Million 5.5 and 10 Year N...  \n",
       "1    Jollibee Foods Corporation (JFC) and Dim Sum P...  \n",
       "2                            Cash dividend declaration  \n",
       "3                  Update of Corporate Contact Details  \n",
       "4    JFC to increase investment in Buyer of Tim Ho ...  \n",
       "..                                                 ...  \n",
       "140  JFC Mandates Banks for U.S.$ Senior Unsecured ...  \n",
       "141  Notice of annual stockholders' meeting for the...  \n",
       "142  Press Release: 2020 1st Quarter Financial Results  \n",
       "143  JFC to Spend Php7 Billion for Business Transfo...  \n",
       "144  JFC’s Earnings Call for its First Quarter 2020...  \n",
       "\n",
       "[145 rows x 10 columns]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dpse.disclosures_combined"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "#!pip install nltk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[nltk_data] Downloading package vader_lexicon to\n",
      "[nltk_data]     /home/jgendrinal/nltk_data...\n",
      "[nltk_data]   Package vader_lexicon is already up-to-date!\n"
     ]
    }
   ],
   "source": [
    "import nltk\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "from nltk.sentiment.vader import SentimentIntensityAnalyzer\n",
    "nltk.download('vader_lexicon')\n",
    "\n",
    "sia = SentimentIntensityAnalyzer()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# nltk.download('punkt')\n",
    "# nltk.download('averaged_perceptron_tagger')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "date_sentiments = {}\n",
    "for idx,row in dpse.disclosures_combined.iterrows():\n",
    "    date = row['Announce Date and Time']\n",
    "    paragraph = row['Background/Description of the Disclosure']\n",
    "    if paragraph is not None:\n",
    "        #split paragraph into sentences \n",
    "    #     sentences = nltk.sent_tokenize(paragraph)\n",
    "    #     for sentence in sentences: \n",
    "    #         sentiment = sia.polarity_scores(sentence)['compound']\n",
    "        sentiment = sia.polarity_scores(paragraph)['compound']\n",
    "        date_sentiments[date] = sentiment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{Timestamp('2020-06-25 07:37:00'): 0.9538,\n",
       " Timestamp('2020-06-19 08:01:00'): 0.8176,\n",
       " Timestamp('2020-06-17 10:39:00'): 0.8658,\n",
       " Timestamp('2020-05-28 07:23:00'): 0.6908,\n",
       " Timestamp('2020-05-28 07:17:00'): 0.936,\n",
       " Timestamp('2020-05-22 11:03:00'): 0.7096,\n",
       " Timestamp('2020-04-15 07:41:00'): 0.9796,\n",
       " Timestamp('2020-04-07 10:16:00'): 0.8807,\n",
       " Timestamp('2020-03-20 07:16:00'): 0.8074,\n",
       " Timestamp('2020-03-16 12:49:00'): 0.4939,\n",
       " Timestamp('2020-03-13 15:49:00'): 0.0,\n",
       " Timestamp('2020-02-18 15:26:00'): 0.0,\n",
       " Timestamp('2020-02-04 09:34:00'): 0.0,\n",
       " Timestamp('2020-01-24 07:35:00'): 0.0,\n",
       " Timestamp('2020-01-17 08:17:00'): 0.4019,\n",
       " Timestamp('2020-01-09 14:03:00'): 0.4767,\n",
       " Timestamp('2019-11-14 11:38:00'): 0.0,\n",
       " Timestamp('2019-11-14 08:06:00'): 0.4767,\n",
       " Timestamp('2019-11-11 14:52:00'): 0.91,\n",
       " Timestamp('2019-10-07 12:42:00'): 0.0,\n",
       " Timestamp('2019-10-02 15:46:00'): 0.7351,\n",
       " Timestamp('2019-09-24 15:43:00'): 0.4767,\n",
       " Timestamp('2019-09-16 11:10:00'): 0.0,\n",
       " Timestamp('2019-09-06 15:50:00'): 0.7964,\n",
       " Timestamp('2019-09-06 15:17:00'): 0.4215,\n",
       " Timestamp('2019-08-05 15:01:00'): 0.6588,\n",
       " Timestamp('2019-08-01 09:48:00'): 0.7351,\n",
       " Timestamp('2019-07-08 07:32:00'): 0.4404,\n",
       " Timestamp('2019-07-01 13:15:00'): 0.8176,\n",
       " Timestamp('2019-06-28 15:59:00'): 0.0,\n",
       " Timestamp('2019-06-28 15:14:00'): 0.0,\n",
       " Timestamp('2019-06-28 15:11:00'): 0.0,\n",
       " Timestamp('2019-06-28 07:41:00'): 0.4215,\n",
       " Timestamp('2019-05-29 11:41:00'): 0.8316,\n",
       " Timestamp('2019-05-15 14:32:00'): 0.0,\n",
       " Timestamp('2019-04-22 12:36:00'): 0.0,\n",
       " Timestamp('2019-04-11 07:58:00'): 0.0,\n",
       " Timestamp('2019-04-08 14:08:00'): 0.0,\n",
       " Timestamp('2019-04-08 13:58:00'): 0.0,\n",
       " Timestamp('2019-02-14 15:00:00'): 0.0,\n",
       " Timestamp('2019-02-14 14:47:00'): 0.4767,\n",
       " Timestamp('2018-12-21 13:37:00'): 0.4404,\n",
       " Timestamp('2018-12-14 10:51:00'): 0.4767,\n",
       " Timestamp('2018-12-03 08:28:00'): 0.9953,\n",
       " Timestamp('2018-11-19 11:55:00'): 0.6124,\n",
       " Timestamp('2018-11-12 13:07:00'): 0.9862,\n",
       " Timestamp('2018-11-09 14:45:00'): 0.8221,\n",
       " Timestamp('2018-10-15 13:58:00'): 0.4404,\n",
       " Timestamp('2018-10-15 13:52:00'): 0.7351,\n",
       " Timestamp('2018-09-07 08:34:00'): 0.9459,\n",
       " Timestamp('2018-08-14 07:59:00'): 0.0,\n",
       " Timestamp('2018-07-05 11:41:00'): 0.4404,\n",
       " Timestamp('2018-07-05 11:35:00'): 0.8977,\n",
       " Timestamp('2018-07-02 07:45:00'): 0.4767,\n",
       " Timestamp('2018-06-29 15:43:00'): 0.6705,\n",
       " Timestamp('2018-06-29 15:42:00'): 0.8176,\n",
       " Timestamp('2018-06-29 15:41:00'): 0.4767,\n",
       " Timestamp('2018-05-09 15:31:00'): 0.0,\n",
       " Timestamp('2018-05-09 15:11:00'): 0.7783,\n",
       " Timestamp('2018-04-17 10:01:00'): 0.0,\n",
       " Timestamp('2018-04-17 08:38:00'): 0.0,\n",
       " Timestamp('2018-04-11 13:54:00'): 0.4404,\n",
       " Timestamp('2018-04-06 14:38:00'): 0.9774,\n",
       " Timestamp('2018-04-05 08:04:00'): 0.0,\n",
       " Timestamp('2018-03-08 10:23:00'): 0.7351,\n",
       " Timestamp('2018-02-14 08:14:00'): 0.4767,\n",
       " Timestamp('2018-02-13 15:18:00'): 0.0,\n",
       " Timestamp('2018-02-13 14:29:00'): 0.0,\n",
       " Timestamp('2017-12-26 11:09:00'): 0.9627,\n",
       " Timestamp('2017-12-05 12:47:00'): 0.0,\n",
       " Timestamp('2017-11-10 15:00:00'): 0.4404,\n",
       " Timestamp('2017-11-10 14:36:00'): 0.9747,\n",
       " Timestamp('2017-11-02 14:02:00'): 0.985,\n",
       " Timestamp('2017-10-09 13:30:00'): 0.5106,\n",
       " Timestamp('2017-09-19 12:31:00'): 0.0,\n",
       " Timestamp('2017-08-14 11:49:00'): 0.9971,\n",
       " Timestamp('2017-07-05 13:52:00'): 0.4939,\n",
       " Timestamp('2017-07-03 14:14:00'): 0.0,\n",
       " Timestamp('2017-06-30 15:21:00'): 0.8176,\n",
       " Timestamp('2017-05-12 15:49:00'): 0.0,\n",
       " Timestamp('2017-05-11 15:46:00'): 0.0,\n",
       " Timestamp('2017-04-06 07:52:00'): 0.0,\n",
       " Timestamp('2017-04-05 14:56:00'): 0.4939,\n",
       " Timestamp('2017-04-03 08:37:00'): 0.4939,\n",
       " Timestamp('2017-03-29 12:04:00'): 0.3182,\n",
       " Timestamp('2017-03-14 14:45:00'): 0.4767,\n",
       " Timestamp('2017-02-16 07:39:00'): 0.296,\n",
       " Timestamp('2017-02-14 14:47:00'): 0.0,\n",
       " Timestamp('2017-01-03 07:38:00'): 0.836,\n",
       " Timestamp('2016-12-23 12:56:00'): 0.9882,\n",
       " Timestamp('2016-12-15 09:16:00'): 0.0,\n",
       " Timestamp('2016-12-13 08:12:00'): 0.4404,\n",
       " Timestamp('2016-11-23 12:13:00'): 0.807,\n",
       " Timestamp('2016-11-21 07:58:00'): 0.807,\n",
       " Timestamp('2016-11-17 07:44:00'): 0.4019,\n",
       " Timestamp('2016-11-15 09:19:00'): 0.6705,\n",
       " Timestamp('2016-11-11 14:49:00'): 0.8176,\n",
       " Timestamp('2016-08-09 12:22:00'): 0.8016,\n",
       " Timestamp('2016-07-22 16:04:00'): 0.8478,\n",
       " Timestamp('2016-07-22 16:03:00'): 0.7003,\n",
       " Timestamp('2016-05-25 08:28:00'): 0.0,\n",
       " Timestamp('2016-05-25 08:19:00'): 0.4939,\n",
       " Timestamp('2016-05-13 12:06:00'): 0.4404,\n",
       " Timestamp('2016-05-12 14:42:00'): 0.0,\n",
       " Timestamp('2016-04-22 11:18:00'): 0.0,\n",
       " Timestamp('2016-04-11 11:49:00'): 0.4767,\n",
       " Timestamp('2016-04-06 15:20:00'): 0.3182,\n",
       " Timestamp('2016-02-24 08:34:00'): 0.4404,\n",
       " Timestamp('2016-02-15 11:53:00'): 0.6124,\n",
       " Timestamp('2016-02-09 15:24:00'): 0.5423,\n",
       " Timestamp('2016-01-14 08:26:00'): 0.6597,\n",
       " Timestamp('2015-11-23 15:27:00'): 0.8176,\n",
       " Timestamp('2015-11-09 14:43:00'): 0.0,\n",
       " Timestamp('2015-11-09 14:42:00'): 0.7845,\n",
       " Timestamp('2015-11-02 10:12:00'): 0.9838,\n",
       " Timestamp('2015-10-27 08:22:00'): 0.9334,\n",
       " Timestamp('2015-10-13 08:31:00'): 0.4215,\n",
       " Timestamp('2015-10-02 13:49:00'): 0.8176,\n",
       " Timestamp('2015-09-18 09:47:00'): 0.0,\n",
       " Timestamp('2015-08-26 09:16:00'): 0.9081,\n",
       " Timestamp('2015-08-07 13:31:00'): 0.3182,\n",
       " Timestamp('2015-06-29 08:10:00'): 0.9792,\n",
       " Timestamp('2015-06-26 16:03:00'): 0.9792,\n",
       " Timestamp('2015-05-14 08:30:00'): 0.802,\n",
       " Timestamp('2015-05-13 14:57:00'): 0.9538,\n",
       " Timestamp('2015-04-08 08:41:00'): 0.9538,\n",
       " Timestamp('2015-04-08 08:39:00'): 0.7184,\n",
       " Timestamp('2015-02-23 13:41:00'): 0.4767,\n",
       " Timestamp('2015-01-22 14:28:00'): -0.3182,\n",
       " Timestamp('2015-01-09 13:24:00'): 0.8625,\n",
       " Timestamp('2015-01-06 07:51:00'): 0.6124}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "date_sentiments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting Portfolio Value: 100000.00\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "must be real number, not LineBuffer",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-9-a24ff364b1c0>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m    141\u001b[0m     \u001b[0mcerebro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbroker\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msetcommission\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcommission\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0.001\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    142\u001b[0m     \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Starting Portfolio Value: %.2f'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mcerebro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbroker\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgetvalue\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 143\u001b[0;31m     \u001b[0mcerebro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    144\u001b[0m     \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Final Portfolio Value: %.2f'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mcerebro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbroker\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgetvalue\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    145\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/backtrader/cerebro.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m   1125\u001b[0m             \u001b[0;31m# let's skip process \"spawning\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1126\u001b[0m             \u001b[0;32mfor\u001b[0m \u001b[0miterstrat\u001b[0m \u001b[0;32min\u001b[0m \u001b[0miterstrats\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1127\u001b[0;31m                 \u001b[0mrunstrat\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrunstrategies\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miterstrat\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1128\u001b[0m                 \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrunstrats\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrunstrat\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1129\u001b[0m                 \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_dooptimize\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/backtrader/cerebro.py\u001b[0m in \u001b[0;36mrunstrategies\u001b[0;34m(self, iterstrat, predata)\u001b[0m\n\u001b[1;32m   1291\u001b[0m                     \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_runonce_old\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrunstrats\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1292\u001b[0m                 \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1293\u001b[0;31m                     \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_runonce\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrunstrats\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1294\u001b[0m             \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1295\u001b[0m                 \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moldsync\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/backtrader/cerebro.py\u001b[0m in \u001b[0;36m_runonce\u001b[0;34m(self, runstrats)\u001b[0m\n\u001b[1;32m   1650\u001b[0m         '''\n\u001b[1;32m   1651\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0mstrat\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrunstrats\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1652\u001b[0;31m             \u001b[0mstrat\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_once\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1653\u001b[0m             \u001b[0mstrat\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# strat called next by next - reset lines\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1654\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/backtrader/lineiterator.py\u001b[0m in \u001b[0;36m_once\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    295\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    296\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0mindicator\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_lineiterators\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mLineIterator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mIndType\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 297\u001b[0;31m             \u001b[0mindicator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_once\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    298\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    299\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0mobserver\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_lineiterators\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mLineIterator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mObsType\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/backtrader/lineiterator.py\u001b[0m in \u001b[0;36m_once\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    315\u001b[0m         \u001b[0;31m# indicators are each called with its min period\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    316\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpreonce\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_minperiod\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 317\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moncestart\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_minperiod\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_minperiod\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    318\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0monce\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_minperiod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuflen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    319\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/backtrader/indicator.py\u001b[0m in \u001b[0;36moncestart_via_nextstart\u001b[0;34m(self, start, end)\u001b[0m\n\u001b[1;32m    122\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    123\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madvance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 124\u001b[0;31m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnextstart\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    125\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    126\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0monce_via_next\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstart\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/backtrader/lineiterator.py\u001b[0m in \u001b[0;36mnextstart\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    345\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    346\u001b[0m         \u001b[0;31m# Called once for 1st full calculation - defaults to regular next\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 347\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    348\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    349\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mnext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-9-a24ff364b1c0>\u001b[0m in \u001b[0;36mnext\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m     23\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mdate\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdate_sentiments\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     24\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msentiment\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdate_sentiments\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdate\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 25\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlines\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msentiment\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msentiment\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     26\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     27\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.local/lib/python3.8/site-packages/backtrader/linebuffer.py\u001b[0m in \u001b[0;36m__setitem__\u001b[0;34m(self, ago, value)\u001b[0m\n\u001b[1;32m    220\u001b[0m             \u001b[0mvalue\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mvariable\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0mto\u001b[0m \u001b[0mbe\u001b[0m \u001b[0mset\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    221\u001b[0m         '''\n\u001b[0;32m--> 222\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0midx\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mago\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    223\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0mbinding\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbindings\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    224\u001b[0m             \u001b[0mbinding\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mago\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: must be real number, not LineBuffer"
     ]
    }
   ],
   "source": [
    "from __future__ import (absolute_import, division, print_function,\n",
    "                            unicode_literals)\n",
    "import matplotlib.pyplot as pl\n",
    "pl.style.use(\"default\")\n",
    "\n",
    "import backtrader as bt\n",
    "import backtrader.indicators as btind\n",
    "from datetime import datetime\n",
    "import os.path\n",
    "import sys\n",
    "\n",
    "class Sentiment(bt.Indicator):\n",
    "    lines = ('sentiment',)\n",
    "    plotinfo = dict(\n",
    "        plotymargin=0.15,\n",
    "        plothlines=[0],\n",
    "        plotyticks=[1.0, 0, -1.0])\n",
    "    \n",
    "    def next(self):\n",
    "        self.date = self.data.datetime\n",
    "        date = bt.num2date(self.date[0]).date()\n",
    "        prev_sentiment = self.sentiment\n",
    "        if date in date_sentiments:\n",
    "            self.sentiment = date_sentiments[date]\n",
    "        self.lines.sentiment[0] = self.sentiment\n",
    "\n",
    "\n",
    "class SentimentStrat(bt.Strategy):\n",
    "    params = (\n",
    "        ('period', 15),\n",
    "        ('printlog', True),\n",
    "    )\n",
    "\n",
    "    def log(self, txt, dt=None, doprint=False):\n",
    "        ''' Logging function for this strategy'''\n",
    "        if self.params.printlog or doprint:\n",
    "            dt = dt or self.datas[0].datetime.date(0)\n",
    "            print('%s, %s' % (dt.isoformat(), txt))\n",
    "\n",
    "    def __init__(self):\n",
    "        # Keep a reference to the \"close\" line in the data[0] dataseries\n",
    "        self.dataclose = self.datas[0].close\n",
    "        # Keep track of pending orders\n",
    "        self.order = None\n",
    "        self.buyprice = None\n",
    "        self.buycomm = None\n",
    "        self.sma = bt.indicators.SimpleMovingAverage(\n",
    "            self.datas[0], period=self.params.period)\n",
    "        self.date = self.data.datetime\n",
    "        self.sentiment = None\n",
    "        Sentiment(self.data)\n",
    "        \n",
    "    def notify_order(self, order):\n",
    "        if order.status in [order.Submitted, order.Accepted]:\n",
    "            # Buy/Sell order submitted/accepted to/by broker - Nothing to do\n",
    "            return\n",
    "        \n",
    "        # Check if an order has been completed\n",
    "        # Attention: broker could reject order if not enough cash\n",
    "        if order.status in [order.Completed]:\n",
    "            if order.isbuy():\n",
    "                self.log(\n",
    "                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %\n",
    "                    (order.executed.price,\n",
    "                     order.executed.value,\n",
    "                     order.executed.comm))\n",
    "                self.buyprice = order.executed.price\n",
    "                self.buycomm = order.executed.comm\n",
    "            else:  # Sell\n",
    "                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %\n",
    "                         (order.executed.price,\n",
    "                          order.executed.value,\n",
    "                          order.executed.comm))\n",
    "                \n",
    "            self.bar_executed = len(self)     \n",
    "            \n",
    "        elif order.status in [order.Canceled, order.Margin, order.Rejected]:\n",
    "            self.log('Order Canceled/Margin/Rejected')\n",
    "            \n",
    "        # Write down: no pending order\n",
    "        self.order = None\n",
    "        \n",
    "    def notify_trade(self, trade):\n",
    "        if not trade.isclosed:\n",
    "            return\n",
    "\n",
    "        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %\n",
    "                 (trade.pnl, trade.pnlcomm))\n",
    "    \n",
    "    ### Main Strat ###\n",
    "    def next(self):\n",
    "        # log closing price of the series from the reference\n",
    "        self.log('Close, %.2f' % self.dataclose[0])\n",
    "        \n",
    "        date = bt.num2date(self.date[0]).date()\n",
    "        prev_sentiment = self.sentiment\n",
    "        if date in date_sentiments:\n",
    "            self.sentiment = date_sentiments[date]\n",
    "        \n",
    "        # Check if an order is pending. if yes, we cannot send a 2nd one\n",
    "        if self.order:\n",
    "            return\n",
    "        print(self.sentiment)\n",
    "        # If not in the market and previous sentiment not none\n",
    "        if not self.position and prev_sentiment:\n",
    "            # buy if current close more than sma AND sentiment increased by >= 0.5\n",
    "            if self.dataclose[0] > self.sma[0] and self.sentiment - prev_sentiment >= 0.5:\n",
    "                self.log('BUY CREATE, %.2f' % self.dataclose[0])\n",
    "                self.order = self.buy()\n",
    "                \n",
    "        # Already in the market and previous sentiment not none\n",
    "        elif prev_sentiment:\n",
    "            # sell if current close less than sma AND sentiment decreased by >= 0.5\n",
    "            if self.dataclose[0] < self.sma[0] and self.sentiment - prev_sentiment <= -0.5:\n",
    "                self.log('SELL CREATE, %.2f' % self.dataclose[0])\n",
    "                self.order = self.sell()\n",
    "\n",
    "    def stop(self):\n",
    "        self.log('(MA Period %2d) Ending Value %.2f' %\n",
    "                 (self.params.period, self.broker.getvalue()), doprint=True)\n",
    "        \n",
    "\n",
    "if __name__ == '__main__':\n",
    "    cerebro = bt.Cerebro()\n",
    "    \n",
    "    # Strategy\n",
    "    cerebro.addstrategy(SentimentStrat)\n",
    "\n",
    "    # Data Feed\n",
    "    data = bt.feeds.YahooFinanceData(\n",
    "        dataname = 'JBFCF',\n",
    "        fromdate = min(date_sentiments.keys()),\n",
    "        todate = datetime.now().date(),\n",
    "        reverse = False\n",
    "    )\n",
    "    \n",
    "    cerebro.adddata(data)\n",
    "\n",
    "    cerebro.broker.setcash(100000.0)\n",
    "    cerebro.addsizer(bt.sizers.FixedSize, stake=10)\n",
    "    cerebro.broker.setcommission(commission=0.001)\n",
    "    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())\n",
    "    cerebro.run()\n",
    "    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())\n",
    "    \n",
    "    cerebro.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## rappler news sentiment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from urllib.request import urlopen\n",
    "from bs4 import BeautifulSoup\n",
    "from datetime import datetime\n",
    "import time\n",
    "\n",
    "import nltk\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "from nltk.sentiment.vader import SentimentIntensityAnalyzer\n",
    "# nltk.download('vader_lexicon')\n",
    "\n",
    "sia = SentimentIntensityAnalyzer()\n",
    "\n",
    "base_url = \"http://rappler.com\"\n",
    "\n",
    "page = urlopen(base_url+'/previous-articles?filterMeta=Jollibee').read()\n",
    "soup = BeautifulSoup(page, features=\"html.parser\")\n",
    "posts = soup.findAll(\"div\", {\"class\": \"col-xs-12 col-sm-8\"})\n",
    "\n",
    "date_sentiments = {}\n",
    "for post in posts[:10]: #default up to 50 posts\n",
    "    time.sleep(1)\n",
    "    url = post.a['href']\n",
    "    #date = post.time.text\n",
    "    date_string = post.span.text.split('-')[0].strip()\n",
    "    date = datetime.strptime(date_string, '%b %d, %Y').date()\n",
    "    print(date, base_url+url)\n",
    "    try:\n",
    "        link_page = urlopen(base_url+url).read()\n",
    "    except:\n",
    "        url = url[:-2]\n",
    "        link_page = urlopen(url).read()\n",
    "    link_soup = BeautifulSoup(link_page)\n",
    "    sentences = link_soup.findAll(\"p\")\n",
    "    passage = \"\"\n",
    "    for sentence in sentences:\n",
    "        passage += sentence.text\n",
    "    sentiment = sia.polarity_scores(passage)['compound']\n",
    "    date_sentiments[date] = sentiment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "date_sentiments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from __future__ import (absolute_import, division, print_function,\n",
    "                            unicode_literals)\n",
    "import matplotlib.pyplot as pl\n",
    "pl.style.use(\"default\")\n",
    "\n",
    "import backtrader as bt\n",
    "import backtrader.indicators as btind\n",
    "from datetime import datetime\n",
    "import os.path\n",
    "import sys\n",
    "\n",
    "class Sentiment(bt.Indicator):\n",
    "    lines = ('sentiment',)\n",
    "    plotinfo = dict(\n",
    "        plotymargin=0.15,\n",
    "        plothlines=[0],\n",
    "        plotyticks=[1.0, 0, -1.0])\n",
    "    \n",
    "    def next(self):\n",
    "        self.date = self.data.datetime\n",
    "        date = bt.num2date(self.date[0]).date()\n",
    "        prev_sentiment = self.sentiment\n",
    "        if date in date_sentiments:\n",
    "            print(date_sentiments[date])\n",
    "            self.sentiment = date_sentiments[date]\n",
    "        self.lines.sentiment[0] = self.sentiment\n",
    "\n",
    "\n",
    "class SentimentStrat(bt.Strategy):\n",
    "    params = (\n",
    "        ('period', 15),\n",
    "        ('printlog', True),\n",
    "    )\n",
    "\n",
    "    def log(self, txt, dt=None, doprint=False):\n",
    "        ''' Logging function for this strategy'''\n",
    "        if self.params.printlog or doprint:\n",
    "            dt = dt or self.datas[0].datetime.date(0)\n",
    "            print('%s, %s' % (dt.isoformat(), txt))\n",
    "\n",
    "    def __init__(self):\n",
    "        # Keep a reference to the \"close\" line in the data[0] dataseries\n",
    "        self.dataclose = self.datas[0].close\n",
    "        # Keep track of pending orders\n",
    "        self.order = None\n",
    "        self.buyprice = None\n",
    "        self.buycomm = None\n",
    "        self.sma = bt.indicators.SimpleMovingAverage(\n",
    "            self.datas[0], period=self.params.period)\n",
    "        self.date = self.data.datetime\n",
    "        self.sentiment = None\n",
    "        Sentiment(self.data)\n",
    "        \n",
    "    def notify_order(self, order):\n",
    "        if order.status in [order.Submitted, order.Accepted]:\n",
    "            # Buy/Sell order submitted/accepted to/by broker - Nothing to do\n",
    "            return\n",
    "        \n",
    "        # Check if an order has been completed\n",
    "        # Attention: broker could reject order if not enough cash\n",
    "        if order.status in [order.Completed]:\n",
    "            if order.isbuy():\n",
    "                self.log(\n",
    "                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %\n",
    "                    (order.executed.price,\n",
    "                     order.executed.value,\n",
    "                     order.executed.comm))\n",
    "                self.buyprice = order.executed.price\n",
    "                self.buycomm = order.executed.comm\n",
    "            else:  # Sell\n",
    "                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %\n",
    "                         (order.executed.price,\n",
    "                          order.executed.value,\n",
    "                          order.executed.comm))\n",
    "                \n",
    "            self.bar_executed = len(self)     \n",
    "            \n",
    "        elif order.status in [order.Canceled, order.Margin, order.Rejected]:\n",
    "            self.log('Order Canceled/Margin/Rejected')\n",
    "            \n",
    "        # Write down: no pending order\n",
    "        self.order = None\n",
    "        \n",
    "    def notify_trade(self, trade):\n",
    "        if not trade.isclosed:\n",
    "            return\n",
    "\n",
    "        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %\n",
    "                 (trade.pnl, trade.pnlcomm))\n",
    "    \n",
    "    ### Main Strat ###\n",
    "    def next(self):\n",
    "        # log closing price of the series from the reference\n",
    "        self.log('Close, %.2f' % self.dataclose[0])\n",
    "        \n",
    "        date = bt.num2date(self.date[0]).date()\n",
    "        prev_sentiment = self.sentiment\n",
    "        if date in date_sentiments:\n",
    "            self.sentiment = date_sentiments[date]\n",
    "        \n",
    "        # Check if an order is pending. if yes, we cannot send a 2nd one\n",
    "        if self.order:\n",
    "            return\n",
    "        print(self.sentiment)\n",
    "        # If not in the market and previous sentiment not none\n",
    "        if not self.position and prev_sentiment:\n",
    "            # buy if current close more than sma AND sentiment increased by >= 0.5\n",
    "            if self.dataclose[0] > self.sma[0] and self.sentiment - prev_sentiment >= 0.5:\n",
    "                self.log('BUY CREATE, %.2f' % self.dataclose[0])\n",
    "                self.order = self.buy()\n",
    "                \n",
    "        # Already in the market and previous sentiment not none\n",
    "        elif prev_sentiment:\n",
    "            # sell if current close less than sma AND sentiment decreased by >= 0.5\n",
    "            if self.dataclose[0] < self.sma[0] and self.sentiment - prev_sentiment <= -0.5:\n",
    "                self.log('SELL CREATE, %.2f' % self.dataclose[0])\n",
    "                self.order = self.sell()\n",
    "\n",
    "    def stop(self):\n",
    "        self.log('(MA Period %2d) Ending Value %.2f' %\n",
    "                 (self.params.period, self.broker.getvalue()), doprint=True)\n",
    "        \n",
    "if __name__ == '__main__':\n",
    "    cerebro = bt.Cerebro()\n",
    "    \n",
    "    # Strategy\n",
    "    cerebro.addstrategy(SentimentStrat)\n",
    "\n",
    "    # Data Feed\n",
    "    data = bt.feeds.YahooFinanceData(\n",
    "        dataname = 'JBFCF',\n",
    "        fromdate = min(date_sentiments.keys()),\n",
    "        todate = datetime.now().date(),\n",
    "        reverse = False\n",
    "    )\n",
    "    \n",
    "    cerebro.adddata(data)\n",
    "\n",
    "    cerebro.broker.setcash(100000.0)\n",
    "    cerebro.addsizer(bt.sizers.FixedSize, stake=10)\n",
    "    cerebro.broker.setcommission(commission=0.001)\n",
    "    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())\n",
    "    cerebro.run()\n",
    "    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())\n",
    "    \n",
    "    cerebro.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
